<template>
  <div class="my-cu-view">
    <div class="title">
      <div class="title-font">{{ title }}</div>
      <div class="back">
        <div @click="goBack"><i class="el-icon-back"></i>返回</div>
      </div>
    </div>
    <el-form :model="form" label-position="left" label-width="90px" ref="form" :rules="rules">
      <el-row :gutter="20" class="row">
        <el-col :span="6">
          <p class="tip">基本信息</p>
          <div style="margin-left: 10px">
            <el-form-item label="用例名称" prop="name">
              <el-input v-model="form.name" autocomplete="off" maxlength="50"></el-input>
            </el-form-item>
            <el-form-item label="所属分类" prop="sceneId">
              <el-select v-model="chooseName" placeholder="请选择" ref="selectSceneId" style="width: 100%;">
                <el-option hidden :key="form.sceneId" value="一级菜单" :label="chooseName"></el-option>
                <el-tree
                  :data="SceneTree"
                  :props="defaultProps"
                  @node-click="nodeOnclick"
                  :expand-on-click-node="false"
                  :check-on-click-node="true"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="用例等级" prop="level">
              <el-select v-model="form.level" placeholder="请选择用例等级" style="width: 100%;">
                <el-option label="P0" value="0"></el-option>
                <el-option label="P1" value="1"></el-option>
                <el-option label="P2" value="2"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="用例描述" prop="description" style="width: 100%">
              <el-input type="textarea" v-model="form.description" autocomplete="off"
                        :autosize="{ minRows: 2, maxRows: 4}" maxlength="200"></el-input>
            </el-form-item>
          </div>
          <p class="tip">配置信息</p>
          <div style="margin-left: 10px">
            <el-form-item label-width="150px" prop="isHandless">
              <span slot="label">
                     <span class="span-box">
                       <span>性能模式</span>
                        <el-tooltip
                          style="diaplay:inline" effect="dark"
                          placement="top">
                          <div slot="content">性能模式能减少内存和cpu的占用，启用后程序在后台运行，不调起浏览器</div>
                          <i class="el-icon-info"/>
                        </el-tooltip>
                     </span>
                   </span>
              <el-switch
                v-model="form.isHandless"
                :active-value=1
                :inactive-value=0
              ></el-switch>
            </el-form-item>
            <el-form-item label="出现异常截图" label-width="150px" prop="isShot">
              <el-switch
                v-model="form.isShot"
                :active-value=1
                :inactive-value=0
              ></el-switch>
            </el-form-item>
            <el-form-item label="结束关闭浏览器" label-width="150px" prop="isEndClose">
              <el-switch
                v-model="form.isEndClose"
                :active-value=1
                :inactive-value=0
              ></el-switch>
            </el-form-item>
            <el-form-item label="忽略异常并继续执行" label-width="150px" prop="isContinueRun">
              <el-switch
                v-model="form.isContinueRun"
                :active-value=1
                :inactive-value=0
              ></el-switch>
            </el-form-item>
          </div>
          <p class="tip">数据驱动</p>
          <div style="margin-left: 10px">
            <el-form-item label-width="120px">
              <span slot="label">
                     <span class="span-box">
                       <span>驱动文件</span>
                        <el-tooltip
                          style="diaplay:inline" effect="dark"
                          placement="top">
                          <div slot="content">1.只能上传单个xls、xlsx文件，且不超过5M
                          <br/>2.文件首行标题 = 变量名，行内容 = 变量值
                          <br/>3.文件变量名和场景变量名重复，按文件的变量值执行
                        </div>
                          <i class="el-icon-info"/>
                        </el-tooltip>
                     </span>
                   </span>
              <el-upload class="upload-demo" :file-list="form.fileList" :before-upload="beforeUpload"
                         :http-request="uploadFile"
                         accept=".xls, .xlsx"
                         style="display: inline-block"
                         :on-remove="removeFile" :on-exceed="handleExceed" action="" :limit="1" ref="upload">
                <el-button type="text" style="display: inline-block">点击上传</el-button>
                <el-button type="text" style="display: inline-block" @click.stop="downloadTemplate">下载模板</el-button>
              </el-upload>
            </el-form-item>
          </div>
        </el-col>
        <el-col :span="18" class="my-tree-table">
          <p class="tip">操作步骤</p>
          <el-form-item prop="steps">
            <dragTreeTable
              :data="treeData"
              :onDrag="onTreeDataChange"
              onlySameLevelCanDrag
              :show-overflow-tooltip="true"
              hightRowChange
            >
              <!--              onlySameLevelCanDrag-->
            </dragTreeTable>
          </el-form-item>
          <div class="text">步骤数：{{ treeData.lists.length }}</div>
        </el-col>
      </el-row>
    </el-form>
    <cu-dialog v-if="visible" :dialogVisble="visible" :title="optTitle" @closeDialog="closeDialog"
               :order="treeData.lists.length + 1"
               @refreshList="closeDialog" @addStep="addStep" :editStepData="editStepData"></cu-dialog>
    <report-dialog v-if="reportVisible" :dialogVisble="reportVisible" @closeDialog="closeDialog" reportType="case"
                   :respData="respData"></report-dialog>
    <case-dialog v-if="caseVisible" :dialogVisble="caseVisible" @closeDialog="closeDialog"
                 :order="treeData.lists.length + 1"
                 @referenceData="referenceData"></case-dialog>
    <variable-dialog v-if="variableVisible" :dialogVisble="variableVisible"
                     @closeDialog="closeDialog"></variable-dialog>
    <div v-if="btnShow" class="bottom_btn">
      <div class="btn_item fab-item-title firstBtn"><span @click="openDialog('新建步骤')">新增步骤</span></div>
      <div class="btn_item fab-item-title thirdBtn"><span @click="openCaseDialog">用例引用</span></div>
      <div class="btn_item fab-item-title secondBtn"><span @click="variableVisible = true">场景变量</span></div>
      <div @click="debug" class="btn_item fab-item-title fourthBtn">立即执行</div>
      <div @click="save" class="btn_item fab-item-title fifthBtn">保存用例</div>
    </div>
    <div class="optBtn">
      <el-button icon="el-icon-thumb" circle @click="btnShow = !btnShow" class="hand-btn"></el-button>
    </div>
  </div>
</template>

<script>
import CuDialog from "./cuDialog";
import VariableDialog from "../compoents/variableDialog";
import ReportDialog from "../compoents/reportDialog";
import {deepClone, reMatch, guid} from '@/utils/util'
import CaseDialog from "../compoents/caseDialog";
import dragTreeTable from 'drag-tree-table'

export default {
  name: "cuView",
  components: {VariableDialog, CaseDialog, CuDialog, ReportDialog, dragTreeTable},
  data() {
    let checkSteps = (rule, value, callback) => {
      if (this.treeData.lists.length === 0) {
        callback(new Error('steps不能为空'));
      } else {
        callback();
      }
    };
    return {
      btnShow: true,
      title: "",
      optTitle: "",
      editStepData: {},
      chooseName: "",
      defaultProps: {label: "name", children: "children"},
      form: {
        name: "",
        sceneId: "",
        level: "",
        description: "",
        steps: [],
        isHandless: 0,
        isEndClose: 1,
        isContinueRun: 0,
        isShot: 0,
        fileList: [],
        filePath: "",
        fileName: "",
      },
      SceneTree: [],
      rules: {
        name: [{required: true, message: '用例名称不能为空', trigger: 'blur'}],
        level: [{required: true, message: '用例等级不能为空', trigger: 'change'}],
        sceneId: [{required: true, message: '所属场景不能为空', trigger: 'change'}],
        steps: [{required: true, validator: checkSteps, message: '操作步骤不能为空', trigger: 'change'}]
      },
      visible: false,
      reportVisible: false,
      caseVisible: false,
      variableVisible: false,
      respData: [],
      treeData: {
        custom_field: {
          lists: 'children'
        },
        columns: [
          {
            type: "selection",
            title: '步骤名称',
            field: 'stepName',
            width: 200,
            flex: 1,
            formatter: (item) => {
              return '<span  title=' + item.stepName + '>' + item.stepName + '</span>'
            }
          },
          {
            title: '操作对象',
            field: 'optElement',
            width: 250,
            flex: 1,
            formatter: (item) => {
              if (item.optElement && item.optElement.chooseName !== '') {
                return '<span style="margin-left: 5px;" title=' + '【' + item.optElement.chooseName + '】' + item.optElement.elLabel + '>' + '【' + item.optElement.chooseName + '】〖' + item.optElement.elLabel + '〗' + '</span>'
              } else if (item.optElement && item.optElement.by !== '') {
                return '<span style="margin-left: 5px;" title=' + '【' + item.optElement.by + '】' + item.optElement.expression + '>' + '【' + item.optElement.by + '】〖' + item.optElement.expression + '〗' + '</span>'
              } else {
                return '<span style="margin-left: 5px;">-</span>'
              }
            }
          },
          {
            title: '操作数据',
            field: 'optData',
            width: 250,
            formatter: (item) => {
              if (item.optData && item.optData.length === 1) {
                return '<span style="margin-left: 5px;" title=' + item.optData[0].value + '>' + item.optData[0].value + '</span>'
              } else if (item.optData && item.optData.length === 2) {
                return '<span style="margin-left: 5px;" title=' + item.optData[0].value + '>' + item.optData[0].value + ':' + item.optData[1].value + '</span>'
              } else {
                return '<span style="margin-left: 5px;">-</span>'
              }
            }
          },
          {
            title: '启用状态',
            field: 'status',
            width: 80,
            formatter: (item) => {
              if (item.status === "1" || item.children.length > 0) {
                return '<span style="margin-left: 5px;color: #67c23a">已启用</span>'
              } else {
                return '<span style="margin-left: 5px;text-decoration:line-through;color: #ff0e13 ">已禁用</span>'
              }
            }
          },
          {
            title: '操作',
            type: 'action',
            width: 130,
            actions: [
              {
                text: '克隆',
                onclick: (item) => {
                  // item是当前行的数据
                  let newItem = JSON.parse(JSON.stringify(item))
                  newItem.id = guid()
                  this.treeData.lists.push(newItem)
                },
                formatter: (item) => {
                  if ((item.children && item.children.length === 0 && item.parent_id === 0) || (!item.children && item.parent_id === 0)) {
                    return '<i style="margin-right: 10px;">克隆</i>'
                  }
                }
              },
              {
                text: '编辑',
                onclick: (item) => {
                  // item是当前行的数据
                  this.openDialog('编辑步骤', item)
                },
                formatter: (item) => {
                  if ((item.children && item.children.length === 0 && item.parent_id === 0) || (!item.children && item.parent_id === 0)) {
                    return '<i style="margin-right: 10px;">编辑</i>'
                  }
                }
              },
              {
                text: '删除',
                onclick: (item) => {
                  // item是当前行的数据
                  this.deleteStep(item)
                },
                formatter: (item) => {
                  if (item.parent_id === 0) {
                    return '<i>删除</i>'
                  }
                }
              }
            ]
          },
        ],
        lists: []
      },
      list: [],
    }
  },
  created() {
    this.title = this.$route.query.title
    let caseId = sessionStorage.getItem("caseId")
    if (caseId) {
      this.getCaseInfo(caseId)
      this.$nextTick(() => {
        this.$refs['form'].clearValidate()
      })
    }
  },
  mounted() {
    this.getTreeNode()
  },
  methods: {
    downloadTemplate() {
      this.api({
        url: "/downloadTemplate",
        method: "post",
        responseType: 'blob',
        data: {
          "fileName": "数据驱动模板",
          "sheetName": "数据驱动模板",
          "headerName": "变量名"
        }
      }).then(resp => {
        const link = document.createElement('a');
        let blob = new Blob([resp.data], {type: 'application/vnd.ms-excel'});
        link.style.display = 'none';
        link.href = URL.createObjectURL(blob);
        link.setAttribute('download', decodeURI(resp.headers["filename"]));
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        this.$message({message: "下载模板成功", type: 'success'})
      });
    },
    // 上传前判断格式和大小
    beforeUpload(file) {
      let FileExt = file.name.replace(/.+\./, "");
      if (['xls', 'xlsx'].indexOf(FileExt.toLowerCase()) === -1) {
        this.$message({
          type: 'warning',
          message: '请上传后缀名为xls、xlsx的附件！'
        });
        return false;
      }
      if (file.size > 5 * 1024 * 1024) {
        this.$message.warning('文件大小超过5M 无法上传');
        return false;
      }
      return true;
    },
    handleExceed() {
      this.$message.warning('一次最多只能上传一个文件');
    },
    uploadFile(option) {
      let FormDatas = new FormData()
      console.log(option)
      FormDatas.append('file', option.file);
      this.form.fileList = []
      this.form.fileName = option.file.name;
      this.form.fileList.push(option.file);
      this.api({
        url: "/upload",
        method: "post",
        data: FormDatas,
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(resp => {
        if (resp.code === "500") {
          this.form.fileList = [];
        } else {
          this.form.filePath = resp
        }
      });
    },
    removeFile() {
      this.form.fileList = [];
      this.form.filePath = "";
      this.form.fileName = "";
    },
    getCaseInfo(caseId) {
      this.api({url: `/getCaseInfoById/${caseId}`, method: "get"}).then((resp) => {
        let data = resp
        data.steps = JSON.parse(data.steps)
        data.fileList = data.fileName ? [{"name": data.fileName}] : [];
        this.form = {...data}
        this.chooseName = this.form.sceneName
        this.treeData.lists = data.steps
      })
    },
    // list:更新后的数据源
    // from: 当前被拖拽的行
    // to: 目标拖拽行
    // where: 拖拽的类型，top（上面）、center（里面）、bottom（下面）
    onTreeDataChange(list, from, to, where) {
      this.treeData.lists = list;
    },
    closeDialog() {
      this.visible = false;
      this.reportVisible = false;
      this.caseVisible = false;
      this.variableVisible = false;
    },
    openCaseDialog() {
      this.caseVisible = true;
    },
    referenceData(data) {
      console.log("data=", data)
      this.$message.success("引用：" + `${data[0].stepName}` + " 成功")
      this.treeData.lists = [...this.treeData.lists, ...data]
      this.$refs['form'].clearValidate("steps")
      this.closeDialog()
      console.log("用例引用后的值：", this.treeData.lists)
    },
    goBack() {
      const planId = sessionStorage.getItem("planId");
      const title = sessionStorage.getItem("title");
      planId ? this.$router.push({path: 'planCu', query: {title: title}}) : this.$router.push({"path": "scene"});
    },
    openDialog(title, data = null) {
      this.optTitle = title;
      this.editStepData = data;
      this.visible = true;
    },
    deleteStep(item) {
      let index = this.treeData.lists.indexOf(item)
      if (index !== -1) {
        this.treeData.lists.splice(index, 1)
      }
    },
    getTreeNode() {
      this.api({
        url: `/getSceneTree/${sessionStorage.getItem("projectId")}`,
        method: "get"
      }).then(resp => {
        this.SceneTree = resp.list;
      });
    },
    nodeOnclick(data) {
      // 配置树形组件点击节点后，设置选择器的值，配置组件的数据
      this.chooseName = data.name
      this.form.sceneId = data.id
      // 选择器执行完成后，使其失去焦点隐藏下拉框效果
      this.$refs.selectSceneId.blur()
    },
    save() {
      this.$refs.form.validate(valid => {
        if (valid) {
          let newForm = {}
          newForm = JSON.parse(JSON.stringify(this.form))
          newForm.steps = JSON.stringify(this.treeData.lists);
          if (this.title === "新建用例") {
            newForm.createUser = this.$store.state.user.userId;
            newForm.projectId = sessionStorage.getItem("projectId");
            this.api({url: "/addCase", method: "post", data: newForm}).then(resp => {
              this.goBack();
              this.$message({message: resp, type: 'success'});
            })
          } else {
            newForm.updateUser = this.$store.state.user.userId;
            this.api({url: "/updateCase", method: "put", data: newForm}).then(resp => {
              this.$message({message: resp, type: 'success'});
              this.getCaseInfo(sessionStorage.getItem("caseId"));
            })
          }
        }
      })
    },
    debug() {
      this.$refs.form.validate(valid => {
        if (valid) {
          let newForm = {}
          newForm = JSON.parse(JSON.stringify(this.form))
          newForm.steps = this.treeData.lists
          newForm.projectId = sessionStorage.getItem("projectId")
          newForm.createUser = this.$store.state.user.userId;
          console.log("debug-newForm", newForm)
          this.list = []
          const loading = this.$loading({
            lock: true, // lock的修改符--默认是false
            text: 'Loading', // 显示在加载图标下方的加载文案
            spinner: 'el-icon-loading', // 自定义加载图标类名
            background: 'rgba(0, 0, 0, 0.7)', // 遮罩层颜色
            target: document.querySelector('#table')//loading覆盖的dom元素节点
          })
          this.api({url: "/runCase", method: "post", data: newForm}).then(resp => {
            this.respData = resp[0]
            this.reportVisible = true;
            loading.close()
          })
        }
      })
    },
    addStep(obj) {
      if (!this.treeData.lists) {
        this.treeData.lists = []
      }
      let arr = [...this.treeData.lists]
      let targetIndex = arr.findIndex((item) => item.id === obj.id);
      if (targetIndex === -1) {
        targetIndex = arr.length;
      }
      arr.splice(targetIndex, 1, obj);
      this.treeData.lists = arr
      this.$refs['form'].clearValidate("steps")
    }
  }
}
</script>

<style lang="scss">
.del_line::after {
  content: no-open-quote;
  position: absolute;
  top: 51%;
  left: 0;
  width: 100%;
  border-bottom: 1px solid #000;
}

.my-cu-view {
  margin: 20px;
  background-color: white;
  height: calc(100vh - 110px);

  .tree-column {
    text-align: left;
  }

  .zip-icon {
    width: 14px;
    height: 14px;
    margin-bottom: 5px;
  }

  .text {
    padding: 0 0 10px 0;
    color: #0044f0;
    font-size: 14px;
  }

  .my-tree-table {
    .drag-tree-table-body {
      height: calc(100vh - 311px) !important;
      overflow-y: scroll !important;
    }

    .el-form-item__content {
      margin-left: 0 !important;
    }

    .drag-tree-table {
      margin: 0;
      font-size: 14px;
    }

    .drag-tree-table-header {
      height: 40px;
      line-height: 20px;
      font-weight: 500;
      color: #333;
      background-color: #eee;
    }

    .tree-row {
      height: 48px;
      line-height: 24px;
    }

    .tree-column .align-undefined .colIndex3:hover {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      cursor: pointer;
    }

    .action-item {
      color: #0044F0;
      font-size: 14px;
    }

  }

  .tip {
    padding: 0 5px;
    font-size: 16px;
    border-radius: 0;
    border-left: 4px solid #0044f0;
    font-weight: 700;
  }

  .title {
    height: 50px;
    padding: 0 20px;
    border-bottom: 1px solid #ddd;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex: 0 0 auto;
  }

  .title-font {
    font-size: 20px;
    color: #333;
    line-height: 1;
    font-weight: 700;
  }

  .back {
    position: relative;
    font-size: 14px;
    color: #0044f0;
    line-height: 1;
    cursor: pointer;
  }

  .row {
    padding: 0 20px;
  }

  .bottom_btn {
    position: fixed;
    bottom: 35px;
    right: 80px;

    .firstBtn {
      color: rgb(245, 108, 108);
      background: rgb(252, 241, 241);
    }

    .secondBtn {
      color: rgb(0, 128, 128);
      background: rgb(235, 242, 242);
    }

    .thirdBtn {
      color: rgb(2, 167, 240);
      background: rgb(244, 244, 245);
    }

    .fourthBtn {
      color: rgb(103, 194, 58);
      background: rgb(242, 249, 238);
    }

    .fifthBtn {
      color: rgb(230, 162, 60);
      background: rgb(252, 246, 238);
    }

    .fab-item-title {
      cursor: pointer;
      box-shadow: 0 1px 0.5px #ccc;
      padding: 5px 5px;
      font-size: 14px;
      min-width: 5em;
      white-space: nowrap;
      border-radius: 2px;
      text-align: center;
      display: inline-block;
    }
  }

  .optBtn {
    position: fixed;
    right: 40px;
    color: #FFF;
    bottom: 30px;

    .hand-btn {
      background-color: #0044f0 !important;
      border-color: #0044f0 !important;
      color: white;
    }
  }
}


</style>
